/*
* main.fx
*
* Created on 8-apr-2009, 15:09:43
*/

package fotoboek;

import fotoboek.assets.*;
import fotoboek.assets.stubs.albumTileUI;
import fotoboek.assets.stubs.applicationDesignUI;
import fotoboek.assets.stubs.lButtonUI;
import fotoboek.assets.stubs.rButtonUI;
import fotoboek.Constants;
import fotoboek.parser.FeedParser;
import java.lang.Exception;
import java.lang.Object;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.animation.transition.FadeTransition;
import javafx.animation.transition.PauseTransition;
import javafx.animation.transition.SequentialTransition;
import javafx.animation.transition.TranslateTransition;
import javafx.io.http.HttpRequest;
import javafx.lang.FX;
import javafx.scene.Group;
import javafx.scene.image.Image;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.scene.text.TextOrigin;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.fxd.Duplicator;
import fotoboek.assets.AlbumBar;
import fotoboek.model.model.*;

/**
* @author r.mohammadi
*/

// Sequences which hold the Metadate of Albums and Photos
var photos: Photo[];
var albums: Album[];
var thumbRef:ThumbnailImageView[];
var albumRef:AlbumBar[];
def d = Duplicator{};
var fullImageView:FullImageView;
public var thumbImageView: ThumbnailImageView;
//Represents the Constants class, which holds all the non-changeable values.
var config:Constants = Constants{};
// Location of the photos xml files
var urlFotoBoek:String;
//Vars used for dragging the Content Group
var sy = 0.0;
var ey = 0.0;
public var sceneWidth  : Number = bind scene.width;
public var sceneHeight : Number = bind scene.height on replace oldValue{
        // If in landscape mode while loading is complete
        if(sceneHeight == 240 and loadComplete == true) {
            orientationNormal = false;
            //if still in the album screen, show warning message
            if(currentScreen == 1){
                delete content from scene.content;
                delete application from scene.content;
                alert("Please", "select an album first!");
            }
            //otherwise show the full image view of the first or selected photo
            else{
                if (selectedPhoto == -1){
                        selectedPhoto = 0
                    }
                    delete fullImageView from scene.content;
                    delete photoStack from content.content;
                    showFullPhoto(thumbRef[selectedPhoto].photo);
                    config.SCENE_HEIGHT = sceneHeight as Integer;
                    config.SCENE_WIDTH = sceneWidth as Integer;
                    //leftButton.button.visible = false;
                    //rightButton.button.translateX = config.RIGHT_BUTTON_TRANSLATE_X;
                    //rightButton.button.translateY = config.RIGHT_BUTTON_TRANSLATE_Y;
           }
        }
        else if (sceneHeight == 320){
            orientationNormal = true;
            if(currentScreen == 1 or currentScreen == 0){
                try{
                    insert d.duplicate(content) into scene.content;
                    insert d.duplicate(application) into scene.content;
                }
                finally{
                    content.requestFocus();
                   }
            }
            else if(oldValue == 240 and currentScreen !=1 or currentScreen != 0){
                delete fullImageView from scene.content;
                //insert photoStack into content.content;
                showFullPhoto(thumbRef[selectedPhoto].photo);
                config.SCENE_HEIGHT = sceneHeight as Integer;
                config.SCENE_WIDTH = sceneWidth as Integer;
                //leftButton.button.visible = true;
                //rightButton.button.translateX -= config.RIGHT_BUTTON_TRANSLATE_X;
                //rightButton.button.translateY -= config.RIGHT_BUTTON_TRANSLATE_Y;
                //buttonBar.spacing = config.BAR_SPACING_NORMAL;
                //buttonBar.translate_y = config.BAR_TRANSLATE_Y_NORMAL;
            }

        }
        else if(currentScreen != 1 or currentScreen != 0 and loadComplete == false and sceneHeight == 240){
            delete content from scene.content;
            delete application from scene.content;
            alert("Please", "wait till loading is finished!");
        }
        else if(currentScreen != 1 or currentScreen != 0 and loadComplete == false and sceneHeight == 320){
            insert d.duplicate(content) into scene.content;
            insert d.duplicate(application) into scene.content;
        }        
}
// Identifier which is used for figuring out the current screen that is shown.
public var currentScreen:Integer on replace oldValue{
        if(currentScreen != 3){
            updateSize();
        }
        else if(currentScreen == 1){
            if (selectedAlbum == -1) then selectedAlbum = 0;
        }
        else if (currentScreen == 2 and oldValue != 3){
            selectedPhoto = 0;
            ey=0.0;
            println("selectedP {selectedPhoto} | ey {ey}");            
        }        
    };
var selectedAlbum:Integer on replace oldValue{
    if(currentScreen ==1){
    if (selectedAlbum < 0) then selectedAlbum = sizeof(albumRef)-1; if(selectedAlbum > sizeof(albumRef)-1) then selectedAlbum = 0;
        if(selectedAlbum >= 0 and selectedAlbum <= sizeof(albumRef)-1){
            albumRef[selectedAlbum].isPressed = true;           
            albumRef[oldValue].isPressed = false;
            urlFotoBoek = albumRef[selectedAlbum].album.url;
            if(albumRef[selectedAlbum].albumBar_normal.layoutBounds.maxY > (config.SCENE_HEIGHT - config.CORRECTION_SPACE) or albumRef[selectedAlbum].albumBar_normal.layoutBounds.minY < 0){
                doScroll();
            }           
        }
     }
    };
public var selectedPhoto:Integer on replace oldValue{    
        if (selectedPhoto < 0) then selectedPhoto = sizeof(thumbRef)-1; if(selectedPhoto > sizeof(thumbRef)-1) then selectedPhoto = 0;
            if(selectedPhoto >= 0 and selectedPhoto <= sizeof(thumbRef)-1){
                thumbRef[selectedPhoto].selected = true;
                thumbRef[oldValue].selected = false;
                headerLabel = thumbRef[selectedPhoto].photo.title;
                if(thumbRef[selectedPhoto].bgRect.layoutBounds.maxY > (config.SCENE_HEIGHT - config.CORRECTION_SPACE) or
                thumbRef[selectedPhoto].bgRect.layoutBounds.minY < 0 and
                SLIDE_SHOW.running == false){
                    doScroll();
                }
            }        
    };
public var isDragging:Boolean = false;
public var buttonBarShown:Boolean on replace{
        if (buttonBarShown == true){
            BUTTON_BAR_INTRO.stop();
            BUTTON_BAR_OUTRO.stop();
            BUTTON_BAR_INTRO.playFromStart();
        }
        if (buttonBarShown == false){
            BUTTON_BAR_INTRO.stop();
            BUTTON_BAR_OUTRO.stop();
            BUTTON_BAR_OUTRO.playFromStart();
        }
    };
// Booleans, which are used for identifing if the application is loading data
var loadComplete:Boolean on replace{
    // If the loading is done, start playing the outro fading transition
    if(loadComplete == true){
        buttonBar.content.visible = true;
        selectedAlbum = -1;
        selectedPhoto = -1;
        INFO_OUTRO.stop();
        INFO_OUTRO.playFromStart();
    }
    // Else insert the info Group back into the scene and start playing the intro fading transition.
    else {
        buttonBar.content.visible = false;
        insert info into scene.content;
        INFO_INTRO.stop();
        INFO_INTRO.time = 400ms;
        INFO_INTRO.play();
    }
};
var photoLoadComplete:Boolean;
var albumLoadComplete:Boolean;
//Boolean which is used to keep track of the current orientation
var orientationNormal:Boolean = true on replace oldValue{
    if(orientationNormal == false){       
        content.focusTraversable = background.logo.visible = buttonBarShown = application.visible = false;

    }
    else if(oldValue == false){        
        content.focusTraversable = background.logo.visible = buttonBarShown = application.visible = true;
        content.requestFocus();
    }

};

// Containers, for the albums and photos, Items will be added to these containers in runtime
def albumStack:VBox = VBox {
    spacing:config.ALBUM_STACK_SPACING
    translateY: config.ALBUM_STACK_TRANSLATE_Y
}
def photoStack:HBox = HBox {
    spacing: config.PHOTO_STACK_SPACING
    translateY: config.PHOTO_STACK_TRANSLATE_Y
}

// Title string, is bound to the headerLabel of the application
var headerLabel:String = "Photobook" on replace{
    titleBar.text = headerLabel;
};

// .FXD references/ UIStubs
def RIGHT_BUTTON_UI : rButtonUI = rButtonUI{ }
def LEFT_BUTTON_UI : lButtonUI = lButtonUI{ }
def APPLICATION_UI: applicationDesignUI = applicationDesignUI{}

//Right and Left buttons, which handles the navigation and performs other actions like closing the app and showing the photo.
def rightButton:Button = Button{
    rightPadding: config.BUTTON_PADDING
    button: RIGHT_BUTTON_UI._rButton
    text:"Open"
    action:onRightSoftKey
};
def leftButton:Button = Button{
    button: LEFT_BUTTON_UI._lButton;
    text:"Close"
    action:onLeftSoftKey
};
//Holder of the buttons, represents the button bar UI component
def buttonBar:ButtonBar = ButtonBar{
    leftButton:leftButton.button
    rightButton:rightButton.button
    spacing:config.BAR_SPACING_NORMAL
    translate_y:config.BAR_TRANSLATE_Y_NORMAL
}
//Represents the title bar UI component of the application
def titleBar:TitleBar = TitleBar{
    UIAssets:APPLICATION_UI.assets
    text:headerLabel
}
//Represents the background UI
def background:Background = Background{
    UIAssets:APPLICATION_UI.assets
}
//Represents the total application UI component, which holds the title and button bar
def application:Group = Group{
    content:[
            titleBar.content,
            buttonBar.content
        ]
    }
//represents the content holder UI component, which holds the album and photo Stacks
public def content:Group = Group{
    translateY:bind ey
    focusTraversable:true
    onMousePressed: function( e: MouseEvent ):Void {
        isDragging = false;
        sy = e.dragY - ey;
    }
    onMouseDragged:function(e:MouseEvent):Void{
        isDragging = true;
        ey = e.dragY - sy;
        updateSize();
        if(ey > 0) { SCROLL_ANIMATION.playFromStart(); }
        else if(ey < config.MAX_HEIGHT + config.MAX_Y) { ey = config.MAX_HEIGHT + config.MAX_Y}
    }
    onMouseReleased:function(e:MouseEvent):Void{
        isDragging = false;
    }
    onKeyPressed:function(e:KeyEvent) {        
        if(e.code == KeyCode.VK_LEFT) {           
            onLeftArrowKey();
        } else if(e.code == KeyCode.VK_RIGHT) {
            onRightArrowKey();
        } else if (e.code == KeyCode.VK_SOFTKEY_1){
            onRightSoftKey();
        } else if (e.code == KeyCode.VK_SOFTKEY_0){
            onLeftSoftKey();
        } else if(e.code == KeyCode.VK_UP) {
            onUpArrowKey();
        } else if(e.code == KeyCode.VK_DOWN) {
            onDownArrowKey();
        } else if(e.code == KeyCode.VK_ENTER) {
            onEnterKey();
        }
    }
}
// Value of the progress, this value is binded to the progress value of the progress bar.
// Progress bar, which is shown when the application is loading.
var progress:Integer;
def progressBar:ProgressBar = ProgressBar{
    progress:bind progress
    translateX:config.PROGRESS_TRANSLATE_X
    translateY:config.PROGRESS_TRANSLATE_Y
}
// Description which is shown while loading or alerting the user
public var description:String;
// Information group, which contains a description and the progress bar, it's shown when the loadComplete value is false.
def info = Group {
    content:[
        Text{
            content:bind description
            textAlignment:TextAlignment.CENTER
            textOrigin:TextOrigin.TOP
            font: Font.font( "Arial-BoldMT", FontWeight.BOLD, 10)
            x:config.INFO_POS_X
            y:config.INFO_POS_Y
        },
        progressBar
    ]
}
// Album Stack transitions, used for the intro and outro of the AlbumStack VBox
def ALBUM_STACK_OUTRO = TranslateTransition{
    toX: - 500
    byX: 10
    node: albumStack
    interpolator:Interpolator.EASEIN
    duration:2s
    action: function() {
        delete albumStack from content.content;
        loadPhotoMetadata(urlFotoBoek);
        content.requestFocus();
    }
}
def ALBUM_STACK_INTRO = TranslateTransition{
    fromX:-500
    toX: 0
    byX: 10
    node:albumStack
    interpolator:Interpolator.EASEOUT
    duration:2s
    action: function() {
        application.toFront();
        content.requestFocus();
    }
}
// Photo Stack transitions, used for the intro and outro of the PhotoStack VBox
def PHOTO_STACK_OUTRO = TranslateTransition{
    toY: - 500
    byY: 10
    node:photoStack
    interpolator:Interpolator.EASEIN
    duration:2s
    action: function() {
        delete photoStack from content.content;
        photos = null;
        content.requestFocus();
    }
}
def PHOTO_STACK_INTRO = TranslateTransition{
    fromY:-500
    toY: 30
    byY: 10
    node:photoStack
    interpolator:Interpolator.EASEOUT
    duration:2s
    action: function() {        
        application.toFront();
        photoStack.toBack();
        content.requestFocus();
    }
}
// Intro and outro fading transitions for the Information Group.
def INFO_OUTRO = FadeTransition{
    duration:2000ms
    byValue:0.1
    fromValue: 1.0
    toValue:0.0
    node:info
    interpolator: Interpolator.EASEBOTH
    action:function ():Void{
        delete info from scene.content;
        content.requestFocus();
    }
}
def INFO_INTRO = FadeTransition{
    duration:500ms
    fromValue: 0.5
    toValue:1.0
    node:info
    interpolator: Interpolator.EASEBOTH
}
// Intro and outro fading transitions for the Buttons and Header Group.
def BUTTON_BAR_OUTRO = FadeTransition{
    duration:500ms
    toValue:0.0
    node:application
    interpolator: Interpolator.EASEBOTH
    action: function() {
        content.requestFocus();
    }
}
def BUTTON_BAR_INTRO = FadeTransition{
    duration:500ms
    toValue:1.0
    node:application
    interpolator: Interpolator.EASEBOTH
    action: function() {
        content.requestFocus();
    }
}
// Animation which is played when an alert message needs to be shown
def ALERT_ANIMATION = SequentialTransition {
    node: info
    interpolator: Interpolator.EASEBOTH
    content: [
        FadeTransition { duration: 500ms fromValue: 0.0 toValue: 1.0},
        PauseTransition { duration: 2s }, // wait 2 seconds
        FadeTransition { duration: 1500ms fromValue: 1.0 toValue: 0.0 action: function() {delete info from scene.content; progressBar.visible = true;}}
    ]
}
def SCROLL_ANIMATION = Timeline {    
    keyFrames : [    
        KeyFrame {
            time : 500ms
            canSkip : true
            values: [ ey => 0.0 tween Interpolator.EASEOUT ]
        }
    ]
}
def SLIDE_SHOW = Timeline{
    repeatCount:Timeline.INDEFINITE
     keyFrames : [    
        KeyFrame {
            time : 5s
            canSkip : true
            action:showNextPhoto
        }
    ]
}

/*
* Functions which are responsible for the navigation key actions
*/
function onLeftSoftKey():Void{
    if(currentScreen == 1){
            FX.exit();
            println("Sluit");
        }
        else if(currentScreen == 2){
            showScreen("photo", "album");         
            println("Go to Album Stack");
        }
        else if(currentScreen == 3){
            if(SLIDE_SHOW.running == true){
                SLIDE_SHOW.stop();
            }
            showScreen("full", "photo");
            
            println("Go to Photo Stack");
        }
    }
function onRightSoftKey():Void{
    if(currentScreen == 1){
        if(selectedAlbum == -1)then selectedAlbum = 0;
         showScreen("album","home");
        }
        else if(currentScreen == 2){
            println("Toon foto in groot formaat");
            showFullPhoto(thumbRef[selectedPhoto].photo);
        }
        else if(currentScreen == 3){
            if(SLIDE_SHOW.running == true){
                SLIDE_SHOW.stop();
                rightButton.text = "Play";
                
            }
            else {
                SLIDE_SHOW.playFromStart();
                rightButton.text = "Stop";
            }
        }
}
function onLeftArrowKey():Void {
    println("Pressed Left Key");
      if (currentScreen == 2){
         selectedPhoto -= ((thumbRef.size())/config.MAX_COLS);
         println("Met links {selectedPhoto}");
        }
            else if (currentScreen == 3){
                showPreviousPhoto();
            }
}
function onRightArrowKey():Void {
    println("Pressed Right Key");
     if (currentScreen == 2){
            selectedPhoto += ((thumbRef.size())/config.MAX_COLS);
            println("Met rechts {selectedPhoto}");
        }
            else if (currentScreen == 3){
                showNextPhoto();
            }
}
function onUpArrowKey() :Void{
    println("Pressed Up Key");
    if (currentScreen == 1){          
        selectedAlbum --;
    }
        else if (currentScreen == 2){           
            selectedPhoto --;
        }
            else if (currentScreen == 3){
                showPreviousPhoto();
            }
}
function onDownArrowKey() :Void{
    println("Pressed Down Key");
    if (currentScreen == 1){        
        selectedAlbum ++;
    }
        else if (currentScreen == 2){
            selectedPhoto ++;
        }
            else if (currentScreen == 3){
                showNextPhoto();
            }           
}
function onEnterKey():Void{
       if (currentScreen == 1){
            if (selectedAlbum == -1){
                selectedAlbum = 0
            }
            showScreen("album", "home");
        }
            else if (currentScreen == 2){
                if (selectedPhoto == -1){
                    selectedPhoto = 0
                }
                showFullPhoto(thumbRef[selectedPhoto].photo);
            }
            else if (currentScreen == 3 and orientationNormal == true){
                buttonBarShown = not buttonBarShown;
            }
    }
/*
* Function for loading the Album MetaData
*/
function loadAlbumMetadata(location:String):Void {
    //println("### Loading album metadata... ###");
    delete albums;
    description = "Loading albums...";
    headerLabel = "Loading";
    loadComplete = false;
    albumLoadComplete = false;
    var loadProgress:String;
    var httpRequestError: Boolean = false;
    // Submit HttpRequest
    var request: HttpRequest = HttpRequest {
    location: location
    method: HttpRequest.GET
    onRead: function(bytes: Long) {
        // The toRead variable is non negative only if the server provides the content length
        loadProgress = if (request.toread > 0) "{(bytes * 100 / request.toread)}%" else "";
        progress = (bytes * 100 / request.toread);
        description = "Loading albums... {loadProgress}";
        //println("## Loading Albums... ({loadProgress}) ##");
    }
    onException: function(exception: Exception) {
        exception.printStackTrace();
        alert("Error", "{exception}");
        httpRequestError = true;
    }
    onResponseCode: function(responseCode:Integer) {
        if (responseCode != 200) {
            //println("## Failed, response: {responseCode} {request.responseMessage} ##");
            description = "Failed, response: {responseCode} {request.responseMessage}";
        }
    }
    onInput: function(input: java.io.InputStream) {
        try {
            var parser = FeedParser {
            onDoneAlbum: function( data:Album[] ) {
                albums = data;
                if(not httpRequestError) {
                    progress = 100;
                    loadProgress = "100%";
                    headerLabel = "Albums";
                    description="Finished loading...";
                    //updateImages();
                    //focusOnGrid = true;
                    if(albums != null){
                        println("## Populate AlbumStack ##!");
                        populateAlbumStack();
                    }
                }
            }
            };
            parser.parseAlbums(input);
            if(parser.errorMessage.length() > 0) {
                description="Something went wrong... Check internet connection";
                alert("Error", parser.errorMessage);
                httpRequestError = true;
            }
        } finally {
            input.close();
        }
    }
    }
  request.start();
}
/*
* Function which populates the albumStack VBox
*/
function populateAlbumStack():Void{
    delete albumStack.content;  
    var i=0;
    var albumBarUI: albumTileUI;
    for(album in albums){
        album.id = i;
        albumBarUI = albumTileUI{};
        var al = AlbumBar{
            skin:albumBarUI.skin
            nameText : album.name;
            captionText : trimString(album.caption, 30);
            itemsText : "{album.items} Photo's |";
            ownerText : "By: {album.photographer}";
            album: album
            coverImage: Image{
                url:album.cover
                height: config.ALBUM_COVER_HEIGHT
                width: config.ALBUM_COVER_WIDTH
                backgroundLoading:true
                preserveRatio:false
                smooth:false
            }
            action: function():Void {
                if (not isDragging){                  
                    selectedAlbum = album.id as Integer;
                    showScreen("album", "home");
                }
            }
        };
        i++;
        //Insert the AlbumBar node into the VBox albumStack,
        //by appending it to the contents sequence.
        insert d.duplicate(al.skin) into albumStack.content;
        insert al into albumRef;       
    }
    loadComplete = albumLoadComplete = true;
    delete albums;
    showScreen("home","album");
}
/*
* Function for loading the Photo MetaData, from a chosen album
*/
function loadPhotoMetadata(location:String):Void {
    delete photos;
    delete thumbRef;
    loadComplete = photoLoadComplete = false;
   // println("### Loading photo metadata...###");
    description = "Loading photo's...";
    headerLabel = "Loading";
    var loadProgress:String;
    var httpRequestError: Boolean = false;
    // Submit HttpRequest
    var request: HttpRequest = HttpRequest {
        location: location
        method: HttpRequest.GET
        onRead: function(bytes: Long) {
            // The toread variable is non negative only if the server provides the content length
            loadProgress = if (request.toread > 0) "{(bytes * 100 / request.toread)}%" else "";
            progress = (bytes * 100 / request.toread);
            description = "Loading photo's... ({loadProgress})";
        }
        onException: function(exception: Exception) {
            exception.printStackTrace();
            alert("Error", "{exception}");
            httpRequestError = true;
            description = "ERROR: {exception.toString()}";
        }
        onResponseCode: function(responseCode:Integer) {
            if (responseCode != 200) {
                println("## Failed, response: {responseCode} {request.responseMessage} ##");
                description = "Failed, response: {responseCode} {request.responseMessage}";
            }
        }

        onInput: function(input: java.io.InputStream) {            
            try {
                description = "Parsing..";
                var parser = FeedParser {
                onDonePhoto: function( data:Photo[] ) {
                    photos = data;
                    if(not httpRequestError) {
                        progress = 100;
                        loadProgress = "100%";
                        description = "Finished loading...";
                        headerLabel = "Photo's";
                        populatePhotoStack();                        
                    }
                }
                };
                parser.parsePhotos(input);
                if(parser.errorMessage.length() > 0) {
                    alert("Error", parser.errorMessage);
                    httpRequestError = true;
                    description="Something went wrong, check internet connection...";
                }
            } finally {
                input.close();
            }
        }
    }
request.start();
}
/*
* Function which populates the photoStack VBox
*/
function populatePhotoStack():Void{
    //println("### Start Photo Populating ###");
    delete photoStack.content;
    description ="Creating thumbnails";
    def items = photos.size();
    def maxCols = config.MAX_COLS;
    def maxRows = items / maxCols;
    
    var vBox: VBox;
    var i = 0;
   // println("Items: {items} / maxCols: {maxCols} = maxRows: {maxRows -1} ");
    for(col in [0..(maxCols - 1)]) {
        vBox = VBox{spacing:0;};
        for(row in [0..(maxRows - 1)]) {
            photos[i].id = i;
            def thumbUrl = "{photos[i].url}{photos[i].thumbnail}";
            thumbImageView = ThumbnailImageView{
                index:photos[i].id
                width: config.THUMB_WIDTH
                height: config.THUMB_HEIGHT
                photo:photos[i]
                image:Image{
                    url: thumbUrl
                    width:config.THUMB_WIDTH - 4
                    height:config.THUMB_HEIGHT - 4
                    placeholder: config.PLACEHOLDER
                    preserveRatio:false
                    smooth:false
                    backgroundLoading:true
                }
                action:function():Void{

                }

            }//ThumbnailImageView
            i++;
            if(thumbUrl != ""){
                insert d.duplicate(thumbImageView) into vBox.content;
                insert thumbImageView into thumbRef;
                
            }
        }
        
        insert vBox into photoStack.content;
    }
    loadComplete = photoLoadComplete = true;
    delete photos;   
    showScreen("home","photo");    
}
/*
* Function for showing the full photo
*/
public function showFullPhoto(photo:Photo):Void{
    fullImageView = null;
    delete fullImageView from scene.content;
    def origUrl = "{photo.url}{photo.original}";
    def title = photo.title;
    def width = photo.origWidth;
    def height = photo.origHeight;
    headerLabel = title;
    fullImageView = FullImageView{
        x:0 y:0
        width:bind config.SCENE_WIDTH height: bind config.SCENE_HEIGHT
        image: Image{
            url:origUrl
            height: if(height.equals("640")){config.FULL_MAX_SIZE} else {config.FULL_MIN_SIZE};
            width: if(width.equals("640")){config.FULL_MAX_SIZE} else {config.FULL_MIN_SIZE};
            preserveRatio:true
            backgroundLoading:true
            smooth:false
        }
    }   
    showScreen("photo", "full");
}
/*
 * Functions which shows the previous or next photo as a Full Image
 */
public function showPreviousPhoto():Void{
    try{
        delete fullImageView from scene.content;
    }
    finally{
        selectedPhoto--;
        showFullPhoto(thumbRef[selectedPhoto].photo);
    }
 }
public function showNextPhoto():Void{
    try{
        delete fullImageView from scene.content;
    }
    finally{
        selectedPhoto ++;
        showFullPhoto(thumbRef[selectedPhoto].photo);
    }
 }
/*
* Function for switching between screens
*/
public function showScreen(fromScreen:String, toScreen:String):Void{
    try{
        if(fromScreen.equals("home") and toScreen.equals("album")){
            ey = 0.0;
            currentScreen = 1;
            leftButton.text = "Close";
            rightButton.text = "Open";
            headerLabel = "Albums";
            insert albumStack into content.content;
            println("## Start playing the AlbumStack Intro Animation ##");
            ALBUM_STACK_INTRO.stop();
            ALBUM_STACK_INTRO.playFromStart();

        }
        else if(fromScreen.equals("album") and toScreen.equals("home")){
            currentScreen = 0;
            ALBUM_STACK_OUTRO.stop();
            ALBUM_STACK_OUTRO.playFromStart();
            headerLabel = "Home";

        }
        else if(fromScreen.equals("home") and toScreen.equals("photo")){
            ey = 0.0;
            currentScreen = 2;
            leftButton.text = "Back";
            rightButton.text = "Show";

            insert photoStack into content.content;
            println("## Start playing the PhotoStack Intro Animation ## {ey}");
            PHOTO_STACK_INTRO.stop();
            PHOTO_STACK_INTRO.playFromStart();
        }
        else if(fromScreen.equals("photo") and toScreen.equals("album")){
            try{
                println("## Start playing the PhotoStack Outro Animation ##");
                PHOTO_STACK_OUTRO.stop();
                PHOTO_STACK_OUTRO.playFromStart();
            }
            finally{
                showScreen("home", "album");
            }
        }
        else if(fromScreen.equals("photo") and toScreen.equals("full")){
            if(currentScreen != 3){
                try{
                currentScreen = 3;
                println("## Start playing the PhotoStack Outro Animation ##");
                PHOTO_STACK_OUTRO.stop();
                PHOTO_STACK_OUTRO.playFromStart();
                }
                finally{
                    leftButton.text = "Back";
                    rightButton.text = "Play";
                    insert fullImageView into scene.content;
                    fullImageView.show = true;
                    fullImageView.toFront();
                    println("## FullImage is now shown {selectedPhoto}##");
                }
            }
            else{
                insert fullImageView into scene.content;
                fullImageView.show = true;
                fullImageView.toFront();
            }
        }
        else if(fromScreen.equals("full") and toScreen.equals("photo")){
            try{
                buttonBarShown = true;
                delete fullImageView from scene.content;
                insert application into scene.content;
                currentScreen = 2;
                leftButton.text = "Back";
                rightButton.text = "Show";
            }
            finally{
                insert photoStack into content.content;
                println("## Start playing the PhotoStack Intro Animation ##");
                PHOTO_STACK_INTRO.stop();
                PHOTO_STACK_INTRO.playFromStart();
            }
        }
    }
    finally{
        albumStack.toBack();
        photoStack.toBack();
        application.toFront();
        if(currentScreen == 2) then doScroll();
    }
}
/*
* Function for displaying an alert message
*/
function alert(alertTitle:String, msg:String): Void {
    println("### ALERT ### {msg}");
    description = trimString("{alertTitle}: {msg}", 35);
    progressBar.visible = false;
    insert info into scene.content;
    ALERT_ANIMATION.stop();
    ALERT_ANIMATION.playFromStart();
}
/*
* Trim the string if length is greater than specified length
*/
public function trimString(string:String, length:Integer) : String {
    if(string == null) return "";
    if(string.length() > length) {
        return "{string.substring(0, length).trim()}..";
    } else {
        return string;
}
}
function updateSize():Void{
        config.USED_SPACE = (buttonBar.content.boundsInLocal.height - 50) as Integer;
        config.MAX_Y = scene.width - config.USED_SPACE as Integer;
        config.MEASURED_HEIGHT = content.boundsInLocal.height as Integer;
        config.MAX_HEIGHT = config.MEASURED_HEIGHT-(config.MEASURED_HEIGHT*2);
        println("Size updated");
}
function doScroll() : Void{
    //if(not PHOTO_STACK_INTRO.running or not ALBUM_STACK_INTRO.running){
        def screenSize: Number = config.SCENE_HEIGHT - config.CORRECTION_SPACE;
        var toY:Number;
        var maxY:Number = if(currentScreen == 2){ thumbRef[selectedPhoto].bgRect.layoutBounds.maxY } else {albumRef[selectedAlbum].albumBar_normal.layoutBounds.maxY;}
        var minY:Number = if (currentScreen == 2){thumbRef[selectedPhoto].bgRect.layoutBounds.minY} else {albumRef[selectedAlbum].albumBar_normal.layoutBounds.minY;}
         if(maxY > screenSize){
               toY = ey + (screenSize - maxY);
               println("Do scroll From: Ey {ey} maxY: {maxY} with {toY} To{ey + toY}");
            }
                else if(minY < 0){
                    toY = ey - (0 + (minY - 25));
                }
            Timeline {
                keyFrames : [
                    KeyFrame {
                        time : 500ms
                        canSkip : true
                        values: [ey => toY tween Interpolator.EASEBOTH]
                        action:function():Void{
                            updateSize();
                             if(ey < config.MAX_HEIGHT + config.MAX_Y) { ey = config.MAX_HEIGHT + config.MAX_Y}
                             else if(ey > 0) { SCROLL_ANIMATION.playFromStart(); }
                        }
                    }
                ]
            }
            .playFromStart();
    //}
}

def scene:Scene = Scene {
    width:config.SCENE_WIDTH
    height:config.SCENE_HEIGHT
    fill: config.SCENE_COLOR
    content:[
            background.logo,
            content,
            application,
            //info
        ]
}
def stage:Stage = Stage {
    scene:scene
    style:StageStyle.TRANSPARENT
}
/*
* The init function which is first executed when the application is started
*/
function run() {


//    insert d.duplicate(titleBar.content) into application.content;
//    insert d.duplicate(buttonBar.content) into application.content;
//    insert d.duplicate(info) into scene.content;
//    insert d.duplicate(background.logo) into scene.content;
//    insert d.duplicate(content) into scene.content;
//    insert d.duplicate(application) into scene.content;
    config = Constants{};
    loadAlbumMetadata(config.ALBUM_LOCATION);
    selectedAlbum = -1;
    selectedPhoto = -1;
    buttonBarShown = not buttonBarShown;
    content.focusTraversable = true;
    content.requestFocus();
    return stage;
}